/*
 * Coded by David Bruno Cortarello <Nomius>. Redistribute under the terms of
 * the BSD-lite license. Bugs, suggests, nor projects: nomius@users.berlios.de.
 *
 * Program: Limshsql
 * Version: 1.0
 *
 *
 * Copyright (c) 2005, David B. Cortarello
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of Kwort nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <pwd.h>
#include <sys/types.h>
#include <mysql/mysql.h>
#include <readline/readline.h>

#define NOMCONF "/.nom.conf"
#define NOMSQLCONF "/.nomsql.conf"

MYSQL mysql;
struct passwd *logged_user;
struct tm *fn;
time_t now;


char **atm(char *s){
	int i, j, tok=1;
	char **mat=NULL;
	char separator=' ';
	for(i=0;s[i];i++)
		if(s[i]==separator)
			tok++;
	mat=malloc(sizeof(char *)*tok);
	mat[0]=s;
	for(i=0;i<tok;i++){
		for(j=0;mat[i][j] && mat[i][j]!=separator;j++);
		mat[i+1]=&(mat[i][j+1]);
		mat[i][j]='\0';
	}
	mat[i]=NULL;
	return mat;
}

char **parse_conf_file(){
	char HOME[1024];
	FILE *conf_file;
	char line[1024];
	char **commands;
	int i=0;
	getcwd(HOME, 1024);
	commands=calloc(sizeof(char *), 1024);
	strcat(HOME, NOMCONF);
	if((conf_file=fopen(HOME, "r")) == NULL){
		perror("Error in .nom.conf: ");
		exit(1);
	}
	printf("Loading user configuration");
	while(fscanf(conf_file, " %[^\n]", line)>0){
		commands[i]=calloc(sizeof(char), strlen(line));
		strncpy(commands[i], line, strlen(line));
		i++;
		printf(".");
	}
	printf("  \033[1;32m[done]\033[0;0m\n");
	fclose(conf_file);
	return commands;
}

char **parse_db_file(){
	char HOME[1024];
	FILE *conf_file;
	char line[1024];
	char **db_data;
	int where, i=0;
	getcwd(HOME, 1024);
	db_data=calloc(sizeof(char *), 4);
	strcat(HOME, NOMSQLCONF);
	if((conf_file=fopen(HOME, "r")) == NULL){
		perror("Error in .nomsql.conf: ");
		exit(1);
	}
	printf("Loading configuration database");
	while(fscanf(conf_file, " %[^\n]", line)>0){
		if(strstr(line, "server=")!=NULL) i=0;
		if(strstr(line, "database=")!=NULL) i=1;
		if(strstr(line, "user=")!=NULL) i=2;
		if(strstr(line, "password=")!=NULL) i=3;
		db_data[i]=calloc(sizeof(char), strlen(line));
		where=strcspn(line, "=");
		strcpy(db_data[i], &(line[where+1]));
		printf(".");
		i++;
	}
	printf("  \033[1;32m[done]\033[0;0m\n");
	fclose(conf_file);
	return db_data;
}

void say_about(){
	printf("\nlimshsql v1.0\n");
	printf("   By David Bruno Cortarello (Nomius) <nomius@users.berlios.de>\n\n");
}

void say_help(char **excecute){
	int i=0, j;
	puts("");
	puts("Sysadmin Defined commands:");
	for(;excecute[i];i++){
		printf("\t%d) ", i);
		for(j=0;excecute[i][j] != '='; j++)
			printf("%c", excecute[i][j]);
		printf("\n");
	}
	printf("\nBuilt-in commands\n");
	printf("\thelp \\ ? to see this help\n");
	printf("\tquit \\ exit to exit the system\n");
	printf("\tabout to see the about information\n");
	printf("\n");
}

void ignore(){ ; }

void to_end_sigterm(){
	char record[1024];
	time(&now);
	fn = localtime(&now);
	sprintf(record, "INSERT INTO commands VALUES('Fecha: %d/%d/%d Hora: %d:%d:%d ## Usuario deslogeado: %s')", fn->tm_mday, fn->tm_mon, 1900+fn->tm_year, fn->tm_hour, fn->tm_min, fn->tm_sec, logged_user->pw_name);
	if(mysql_real_query(&mysql, record, strlen(record))!=0){
		mysql_error(&mysql);
		exit (1);
	}
	mysql_close(&mysql);
	exit(0);
}

int main(){
	int i, j, where;
	char *opc;
	char record[2024];
	char *to_excecute=NULL, **params=NULL, **excecute=NULL;
	char **db_init=NULL;
	signal (SIGINT, ignore);
	signal (SIGQUIT, ignore);
	signal (SIGTERM, to_end_sigterm);
	excecute=parse_conf_file();
	db_init=parse_db_file();
	if(mysql_init(&mysql)==NULL){
		exit(1);
	}
	if (!mysql_real_connect(&mysql, db_init[0], db_init[2], db_init[3], NULL, 0, NULL, 0)){
		printf( "Can't connect to mysql server. Error: %s\n", mysql_error(&mysql));
		exit(1);
	}
	if(mysql_select_db(&mysql, db_init[1]) != 0){
		printf( "Can't connect to mysql database. Error: %s\n", mysql_error(&mysql));
		exit(1);
	}
	if(mysql_real_query(&mysql, "CREATE TABLE IF NOT EXISTS commands (executed TEXT NOT NULL)", 60)!=0){
		mysql_error(&mysql);
		exit (1);
	}
	logged_user=getpwuid(getuid());
	time(&now);
	fn = localtime(&now);
	sprintf(record, "INSERT INTO commands VALUES('Fecha: %d/%d/%d Hora: %d:%d:%d ## Usuario logeado: %s')", fn->tm_mday, fn->tm_mon, 1900+fn->tm_year, fn->tm_hour, fn->tm_min, fn->tm_sec, logged_user->pw_name);
	if(mysql_real_query(&mysql, record, strlen(record))!=0){
		mysql_error(&mysql);
		exit (1);
	}
	while(1){
		opc=readline("$> ");
		if(opc==NULL){
			printf("\n");
			break;
		}
		i=atoi(opc);
		if(i == 0  && opc[0] != '0')
			i=-1;
		if(!strcmp("about", opc)){
			say_about();
			continue;
		}
		if(!strcmp("help", opc) || !strcmp("?", opc )){
			say_help(excecute);
			continue;
		}
		if(!strcmp("quit", opc) || !strcmp("exit", opc))
			break;
		if(i == -1) {
			printf("Invalid command... %s\n", opc);
			continue;
		}
		if(i>=0 && excecute[i]){
			time(&now);
			fn = localtime(&now);
			sprintf(record, "INSERT INTO commands VALUES('Hora: %d:%d:%d ## Ejecutado comando: %s')", fn->tm_hour, fn->tm_min, fn->tm_sec, excecute[i]);
			if(mysql_real_query(&mysql, record, strlen(record))!=0){
				mysql_error(&mysql);
				exit (1);
			}
			where=strcspn(excecute[i], "=");
			to_excecute=calloc(sizeof(char), 1024);
			strcpy(to_excecute, where+1+&(excecute[i][0]));
			params=atm(to_excecute);
			if(!fork())
				execvp(to_excecute, params);
			else
				wait(NULL);
		}
		else
			printf("%s not found\n", opc);
	}
	printf("Closing connection with the database... \t");
	time(&now);
	fn = localtime(&now);
	sprintf(record, "INSERT INTO commands VALUES('Fecha: %d/%d/%d Hora: %d:%d:%d ## Usuario deslogeado: %s')", fn->tm_mday, fn->tm_mon, 1900+fn->tm_year, fn->tm_hour, fn->tm_min, fn->tm_sec, logged_user->pw_name);
	if(mysql_real_query(&mysql, record, strlen(record))!=0){
		mysql_error(&mysql);
		exit (1);
	}
	mysql_close(&mysql);
	printf("\033[1;32m[done]\n");
	printf("\033[0;0mWaiting for process to finishing... \t\t");
	wait(NULL);
	printf("\033[1;32m[done]\033[0;0m\n");
	printf("\033[0;0mFreeing used memory... \t\t\t\t");
	if(excecute)
		free(excecute);
	if(db_init)
		free(db_init);
	printf("\033[1;32m[done]\033[0;0m\n");
	exit(0);
}

/* EOF */
